package com.phototodata.service;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 数据库操作服务类
 * 使用 HikariCP 连接池管理数据库连接
 * 实现 UPSERT 操作（存在即更新，不存在则插入）
 *
 * @author PhotoToData
 */
public class DatabaseService {

    private HikariDataSource dataSource;
    private URLClassLoader driverClassLoader; // 保存驱动类加载器引用，避免被 GC

    /**
     * 构造函数：初始化数据库连接池
     *
     * @param jdbcUrl  数据库 JDBC URL
     * @param username 数据库用户名
     * @param password 数据库密码
     */
    public DatabaseService(String jdbcUrl, String username, String password) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(jdbcUrl);
        config.setUsername(username);
        config.setPassword(password);
        
        // 尝试加载达梦数据库驱动类
        boolean driverLoaded = false;
        
        // 方法1：尝试从 classpath 加载
        try {
            Class.forName("dm.jdbc.driver.DmDriver");
            driverLoaded = true;
        } catch (ClassNotFoundException e) {
            // 方法2：尝试从 lib 目录动态加载
            try {
                File driverFile = new File("lib/dmJdbcDriver18.jar");
                if (!driverFile.exists()) {
                    // 尝试从项目根目录查找
                    File projectRoot = new File(System.getProperty("user.dir"));
                    driverFile = new File(projectRoot, "lib/dmJdbcDriver18.jar");
                }
                
                if (driverFile.exists()) {
                    URL[] urls = {driverFile.toURI().toURL()};
                    // 创建 URLClassLoader 并设置为当前线程的上下文类加载器
                    // 保存引用，避免被 GC 回收
                    this.driverClassLoader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
                    Thread.currentThread().setContextClassLoader(this.driverClassLoader);
                    Class.forName("dm.jdbc.driver.DmDriver", true, this.driverClassLoader);
                    driverLoaded = true;
                }
            } catch (Exception ex) {
                // 忽略，继续尝试其他方法
                ex.printStackTrace();
            }
        }
        
        if (!driverLoaded) {
            throw new RuntimeException("无法加载达梦数据库驱动类（dm.jdbc.driver.DmDriver）。" +
                    "\n请确保：\n" +
                    "1. 将 dmJdbcDriver18.jar 文件放到项目的 lib 目录下\n" +
                    "2. 或者运行程序时使用 -cp 参数包含驱动文件，例如：\n" +
                    "   java -cp \"target/PhotoToData-1.0.0.jar;lib/dmJdbcDriver18.jar\" com.phototodata.PhotoToDataApp\n" +
                    "3. 或者将驱动文件添加到系统的 classpath 中");
        }
        
        config.setDriverClassName("dm.jdbc.driver.DmDriver");

        // 连接池配置（轻量级配置）
        config.setMinimumIdle(1);              // 最小空闲连接数
        config.setMaximumPoolSize(5);          // 最大连接池大小
        config.setConnectionTimeout(30000);     // 连接超时时间：30秒
        config.setIdleTimeout(600000);         // 空闲连接超时时间：10分钟
        config.setMaxLifetime(1800000);        // 连接最大生命周期：30分钟
        config.setLeakDetectionThreshold(60000); // 连接泄漏检测阈值：60秒

        // 达梦数据库特定配置
        config.addDataSourceProperty("encoding", "UTF-8");
        config.addDataSourceProperty("schema", ""); // 可选：指定模式名

        this.dataSource = new HikariDataSource(config);
    }

    /**
     * 获取数据库连接
     *
     * @return Connection 对象
     * @throws SQLException 连接异常
     */
    public Connection getConnection() throws SQLException {
        if (dataSource == null) {
            throw new SQLException("数据源未初始化");
        }
        return dataSource.getConnection();
    }

    /**
     * UPSERT 操作：存在即更新，不存在则插入
     * 表：tttt_a01_ext
     * 字段：a00 (文件名), img (Base64 编码的图片数据)
     *
     * @param connection 数据库连接
     * @param fileName   文件名（不含路径）
     * @param base64Image Base64 编码的照片数据
     * @throws SQLException SQL 执行异常
     */
    public void upsertImageData(Connection connection, String fileName, String base64Image) throws SQLException {
        // 先查询是否存在
        String selectSql = "SELECT a00 FROM tttt_a01_ext WHERE a00 = ?";
        boolean exists = false;

        try (PreparedStatement selectStmt = connection.prepareStatement(selectSql)) {
            selectStmt.setString(1, fileName);
            try (ResultSet rs = selectStmt.executeQuery()) {
                exists = rs.next();
            }
        }

        if (exists) {
            // 更新操作
            String updateSql = "UPDATE tttt_a01_ext SET img = ? WHERE a00 = ?";
            try (PreparedStatement updateStmt = connection.prepareStatement(updateSql)) {
                updateStmt.setString(1, base64Image);
                updateStmt.setString(2, fileName);
                int rowsAffected = updateStmt.executeUpdate();
                if (rowsAffected == 0) {
                    throw new SQLException("更新失败：未影响任何行");
                }
            }
        } else {
            // 插入操作
            String insertSql = "INSERT INTO tttt_a01_ext (a00, img) VALUES (?, ?)";
            try (PreparedStatement insertStmt = connection.prepareStatement(insertSql)) {
                insertStmt.setString(1, fileName);
                insertStmt.setString(2, base64Image);
                int rowsAffected = insertStmt.executeUpdate();
                if (rowsAffected == 0) {
                    throw new SQLException("插入失败：未影响任何行");
                }
            }
        }
    }

    /**
     * 关闭数据库连接
     *
     * @param connection 要关闭的连接
     * @throws SQLException 关闭异常
     */
    public void closeConnection(Connection connection) throws SQLException {
        if (connection != null && !connection.isClosed()) {
            connection.close();
        }
    }

    /**
     * 关闭数据源（释放连接池资源）
     */
    public void closeDataSource() {
        if (dataSource != null && !dataSource.isClosed()) {
            dataSource.close();
        }
        // 关闭驱动类加载器（如果存在）
        if (driverClassLoader != null) {
            try {
                driverClassLoader.close();
            } catch (Exception e) {
                // 忽略关闭异常
            }
        }
    }
}

